using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;

namespace IBS.Bll
{
    // Export any type's properties to csv
    public static class CsvExporter
    {
        private static Dictionary<Type, Dictionary<string, Func<object, string>>> map;

        public static string[] GenerateCsvLines<T>(IEnumerable<T> items)
        {
            var headers = cat (GetHeaders<T>());
            var lines = 
                new [] { headers }.Concat(
                    items.Select(obj => cat(map[typeof(T)].Select(p => p.Value(obj)).ToArray())));
            return lines.ToArray();
        }

        public static string[] GetHeaders<T>()
        {
            InitMap<T>();
            return map[typeof(T)].Keys.ToArray();
        }

        private static string cat(string[] items)
        {
            return String.Join(",", items);
        }

        private static void InitMap<T>()
        {
            if(map == null) map = new Dictionary<Type, Dictionary<string, Func<object, string>>>();
            var key = typeof(T);
            if(map.ContainsKey(key))
                return;

            var accessors = key.GetProperties()
                .Where(p => !p.PropertyType.IsGenericType && p.GetIndexParameters().Length == 0)
                .ToDictionary(p => p.Name, p => GetPropertyValueString(p));

            map.Add(key, accessors);
        }

        private static Func<object, string> GetPropertyValueString(PropertyInfo p)
        {
            return obj => {
                var x = p.GetValue(obj, null);
                if(x == null) return String.Empty;
                if(x is DateTime)
                    return ((DateTime)x).ToString("MM/dd/yyyy");
                return x.ToString();
            };      
        }
    }
}

